package com.ql.zk.example;

import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.List;

/**
 * Created by Administrator on 2017/1/9.
 */
public class BaseExcutor implements Watcher {
    private ZooKeeper zk;

    public BaseExcutor(String host, String port) throws IOException {
        String connectStr = host + ":" + port;
        zk = new ZooKeeper(connectStr, 3000, this);
    }

    @Override
    public void process(WatchedEvent event) {
        System.out.println("\n process  start ....");
        String path = event.getPath();
        System.out.println("path  " + path + "  has event!");
        switch (event.getType()) {
            case NodeChildrenChanged:
                System.out.println("path " + path + " NodeChildrenChanged!");
                break;
            case NodeCreated:
                System.out.println("path " + path + " NodeCreated!");
                break;
            case NodeDeleted:
                System.out.println("path " + path + " NodeDeleted!");
                break;
            case None:
                if (event.getState() == Event.KeeperState.SyncConnected) {
                    System.out.println("SyncConnected!");
                } else if (event.getState() == Event.KeeperState.Expired) {
                    System.out.println("Expired!");
                }
                break;
        }
    }

    /**
     * 创建一个给定的目录节点 path, 并给它设置数据，CreateMode
     * 标识有四种形式的目录节点，分别是 PERSISTENT：持久化目录节点，
     * 这个目录节点存储的数据不会丢失；PERSISTENT_SEQUENTIAL：顺序自动编号的目录节点，这种目录节点会根据当前已近存在的节点数自动加 1，
     * 然后返回给客户端已经成功创建的目录节点名；EPHEMERAL：临时目录节点，一旦创建这个节点的客户端与服务器端口也就是 session 超时，这种节点会被自动删除；
     * EPHEMERAL_SEQUENTIAL：临时自动编号节点
     * @param node
     * @param data
     * @param createMode
     * @throws KeeperException
     * @throws InterruptedException
     */

    public void create(String node, String data, CreateMode createMode) throws KeeperException, InterruptedException {
        zk.create(node, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);
    }


    public List<String> list(String node) throws KeeperException, InterruptedException {
        return zk.getChildren(node, true);
    }

    /**
     * 获取这个 path 对应的目录节点存储的数据，数据的版本等信息可以通过 stat 来指定，同时还可以设置是否监控这个目录节点数据的状态
     * @param node
     * @return
     * @throws KeeperException
     * @throws InterruptedException
     */
    public String get(String node) throws KeeperException, InterruptedException {
        return new String(zk.getData(node, true, null));
    }

    /**
     * 给 path 设置数据，可以指定这个数据的版本号，如果 version 为 -1 怎可以匹配任何版本
     * @param node
     * @param value
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void set(String node, String value) throws KeeperException,
            InterruptedException {
        zk.setData(node, value.getBytes(), -1);
    }

    /**
     * 删除 path 对应的目录节点，version 为 -1 可以匹配任何版本，也就删除了这个目录节点所有数据
     * @param node
     * @throws InterruptedException
     * @throws KeeperException
     */
    public void delete(String node) throws InterruptedException,
            KeeperException {
        zk.delete(node, -1);
    }

/*    重载方法，这里给某个目录节点设置特定的 watcher，Watcher 在 ZooKeeper 是一个核心功能，Watcher 可以监控目录节点的数据变化以及子目录的变化，
    一旦这些状态发生变化，服务器就会通知所有设置在这个目录节点上的 Watcher，从而每个客户端都很快知道它所关注的目录节点的状态发生变化，而做出相应的反应*/
    public void exsit(String node) throws KeeperException, InterruptedException {
        zk.exists(node, true);
    }

    public void close() throws InterruptedException {
        zk.close();
    }


    public static void main(String[] args) {
        try {
            BaseExcutor baseExcutor = new BaseExcutor("127.0.0.1", "2181");
            baseExcutor.create("/zk-hg", "hg_1", CreateMode.PERSISTENT);
            baseExcutor.create("/zk-hg/example1", "hg_1_1", CreateMode.PERSISTENT);

            List<String> childNodes = baseExcutor.list("/zk-hg");
            System.out.println("/zk-hg  childNodes are " + childNodes);

            String data1 = baseExcutor.get("/zk-hg/example1");
            System.out.println("/zk-hg/example1 data " + data1);


            baseExcutor.set("/zk-hg/example1", "hg_1_2");
            String data2 = baseExcutor.get("/zk-hg/example1");
            System.out.println("after set /hg/example1 data " + data2);


            baseExcutor.delete("/zk-hg/example1");
            List<String> childNodesDelte = baseExcutor.list("/zk-hg");

            System.out.println("after delete node /zk-hg childNodes are " + childNodesDelte);
            baseExcutor.delete("/zk-hg");
            baseExcutor.close();


        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }
}
